return function(BOXUI)

local utils = BOXUI.utils
local List = BOXUI.list
local lexer = BOXUI.lexer

local M = utils.newclass("codeviewer", List)

local hsl2rgb = utils.hsl2rgb
local clamp = utils.clamp

local hsl = function(H, S, L, A)
	local r, g, b = hsl2rgb((H % 360) / 60, clamp(S, 0, 100) / 100, clamp(L, 0, 100) / 100)
	if not A then return {r, g, b, 1} end
	return {r, g, b, clamp(A, 0, 100) / 100}
end


local default_colors = {
	fore = hsl(0, 0, 0), back = hsl(200, 100, 95), operator = hsl(200, 50, 15),
	keyword = hsl(150, 65, 35), string = hsl(340, 60, 30), comment = hsl(0, 0, 50),
	number = hsl(200, 80, 50), iden = hsl(200, 60, 25), --line = {1 , 0, 0},
	idenlovepre = hsl(340, 75, 60), idenlove = hsl(200, 50, 45),
}

default_colors.activeline = hsl(60, 100, 2)
default_colors.padding = hsl(200, 100, 90)


local operators = {'+', '-', '/', '*', '%', '=', '<', '>', '<=', '>=', '~=', '==', '#'}
for i, v in ipairs(operators) do operators[v] = true end


local insertText = function(t, color, value)
	if value == nil or value == "" then return end
	table.insert(t, color)
	table.insert(t, value)
end

local lnf = function(i) return ("%.3i\t"):format(i) end

local split = utils.split

local loadLua = function(lines, data, colors, haslineno)
	--local lines = {}
	local ln = 1
	local lncolor = colors.comment
	local text = haslineno and {lncolor, lnf(ln)} or {}
	
	local t, tn, color
	for k, v in lexer.lua(data, {}, {}) do
		if operators[k] then k = "operator" end
		t, tn = split(v)
		color = colors[k] or colors.fore
		insertText(text, color, t[1])
		for i = 2, tn do -- nothing happens if tn < 2
			table.insert(lines, {text = text})
			ln = ln + 1
			text = haslineno and {lncolor, lnf(ln)} or {}
			insertText(text, color, t[i])
		end
	end
	if #text > 0 then
		table.insert(lines, {text = text})
		ln = ln + 1
	end
	
	return lines
end

local loadTxt = function(lines, data, color)
	local t = split(data)
	--local lines = {}
	for i, v in ipairs(t) do
		table.insert(lines, {text = {color, v}})
	end
	return lines
end

local fonts

M.loadFile = function(self, filename, refresh)
	if not filename then return end
	local ext = filename:match(".([^.]+)$")
	ext = ext and ext:lower()
	if ext ~= "lua" and ext ~= "txt" then return end
	
	local filedata = love.filesystem.read(filename, 64 * 1024)
	if not filedata then return end
	
	local lines = {}
	
	if ext == "lua" then
		self.font = fonts["small"]
		loadLua(lines, filedata, self.scheme, true)
	elseif ext == "txt" then
		self.font = fonts["big"]
		loadTxt(lines, filedata, self.scheme.fore)
	else
		-- not really
	end
	self.title = filename
	self.filename = filename
	self.extension = ext
	self:setItems(lines, refresh)
end

M.clear = function(self)
	self.title = "No file"
	self.filename = nil
	self.extension = nil
	self:setItems(nil, true)
end

--utils.freshenprops(M.template_theme, theme)

M.init = function(self, x, y, width, height)
	if not fonts then
		fonts = {
			small = love.graphics.newFont(12),
			big = love.graphics.newFont(14)
		}
	end
	self.fonts = fonts
	List.init(self, x, y, width, height)
	--self.list.theme.itemHeight = fonts["big"]:getHeight() + 2
	self.scheme = default_colors
end

BOXUI.add(M)
end

